﻿using Microsoft.Phone.Controls;
using Reuse.PCL.Services;
using System;
using System.Collections.Generic;
using System.Windows.Navigation;

namespace Reuse.WP8.Services {
	/// <summary>
	/// Service to navigate between pages
	/// </summary>
	public class NavigationService : INavigationService {
		private readonly PhoneApplicationFrame frame;
		private Dictionary<string, bool> tombstonedPages;
		public Dictionary<string, Uri> WPRoutingTable { get; set; }
		public Dictionary<string, Type> WSRoutingTable { get; set; }

		public NavigationService( PhoneApplicationFrame frame ) {
			this.frame = frame;
			this.frame.Navigated += frame_Navigated;
			this.frame.Navigating += frame_Navigating;
			this.frame.Obscured += frame_Obscured;
			this.RecoveredFromTombstoning = false;
		}

		public bool CanGoBack {
			get { return this.frame.CanGoBack; }
		}

		public bool RecoveredFromTombstoning { get; set; }


		public bool DoesPageNeedtoRecoverFromTombstoning( Uri pageUri ) {
			if ( !RecoveredFromTombstoning ) return false;

			if ( tombstonedPages == null ) {
				tombstonedPages = new Dictionary<string, bool>();
				tombstonedPages.Add( pageUri.ToString(), true );
				foreach ( var journalEntry in frame.BackStack ) {
					tombstonedPages.Add( journalEntry.Source.ToString(), true );
				}
				return true;
			}

			if ( tombstonedPages.ContainsKey( pageUri.ToString() ) ) {
				return tombstonedPages[pageUri.ToString()];
			}
			return false;
		}

		public void UpdateTombstonedPageTracking( Uri pageUri ) {
			tombstonedPages[pageUri.ToString()] = false;
		}


		public bool Navigate( Uri source ) {
			return this.frame.Navigate( source );
		}

		public bool Navigate(string route) {
			return this.frame.Navigate(WPRoutingTable[route]);
		}
		public bool Navigate( string route, string parameter ) {
			return this.frame.Navigate( new Uri(String.Concat(WPRoutingTable[route].OriginalString, "?id=", parameter), UriKind.Relative) );
		}

		public void GoBack() {
			this.frame.GoBack();
		}
		/// <summary>
		/// Occurs when the content that is being navigated to has been found and is available.
		/// </summary>

		void frame_Navigated( object sender, NavigationEventArgs e ) {
			var handler = this.Navigated;
			if ( handler != null ) {
				handler( sender, e );
			}
		}

		void frame_Navigating( object sender, NavigatingCancelEventArgs e ) {
			var handler = this.Navigating;
			if ( handler != null ) {
				handler( sender, e );
			}
		}

		void frame_Obscured( object sender, ObscuredEventArgs e ) {
			var handler = this.Obscured;
			if ( handler != null ) {
				handler( sender, e );
			}
		}

		event NavigatedEventHandler Navigated;
		event NavigatingCancelEventHandler Navigating;
		event EventHandler<ObscuredEventArgs> Obscured;



		public void Navigate( Type sourcePageType ) {
			throw new NotImplementedException();
		}

		public void Navigate( Type sourcePageType, object parameter ) {
			throw new NotImplementedException();
		}


        public void GoForward()
        {
            this.frame.GoForward();
        }
    }
}
